Release 10.1A: OpenEdge Development:
ADM Reference


Invoking the dynamics call wrapper at the API level

The call wrapper consists of several procedure files with most of the code contained in caller.p. The caller.p file is derived from src/adm2/smart.p, runs as a persistent procedure and is called as a library. A template procedure is provided as a starting point.

A call is broken down into the following phases:

  1. Setup — consists of creating the Parameter Holder temp-table and populating it with new data. The Parameter Holder temp-table is created by a call to one of these functions:
    • setupTTFromSig
    • setupTTFromString
    • setupTTFromTable
  2. Invocation — Before a call can be invoked, a DYNAMIC CALL object is created and properties of the call object are set. The values for these properties are derived from the ttCall temp-table that is defined in the definitions section of caller.p. ttCall is local to and is not exposed in any form to external procedures. When a call is added to ttCall, it is allocated a call number and this is passed as a parameter to the invoke procedure. The values in the ttCall temp-table record are set by a call during the invokeCall procedure from the input parameters to the procedure. As a result, all the attributes of the DYNAMIC CALL handle can be derived from the ttCall temp-table.
  3. Cleanup — Deletes the ttCall record and the following handles:
    • The handle to the call object.
    • The persistent procedure handle if the procedure was instantiated by the dynamics call.
    • The handle to the asynchronous call object.
    • The handle to the Parameter Holder temp-table.

Figure A–4 shows the steps you must make to invoke a call at the API level.

Figure A–4: API calls required to invoke a dynamics call

The calls shown in Figure A–4 illustrate the API calls you need to make to invoke a call:

  1. Create the Parameter Holder temp-table from the parameters using one of the following: setupTTFromSig, setupTTFromString, or setupTTFromTable.
  2. Pass the handle to the Parameter Holder temp-table created in the Step 1, along with all the other parameters to invokeCall.
  3. Use the obtainCallInfo function call to get the required information back on the call. The Parameter Holder temp-table created in Step 1 also contains output parameters and return values.
  4. Use cleanupCall to delete the call handle and any other handles that were created during the invokeCall. Note that it is possible to only delete certain of the handles.

These steps are illustrated in code Example A–12 through Example A–15. Each of the examples makes a call to the internal procedure PROCEDURE emptyProcParam.

Invoking the dynamics call wrapper at an API level requires that you write more code and is more complicated to implement. However, this method of invoking the dynamic call wrapper provides enhanced performance and more control of error handling and the call handle.

For more information about the APIs used to invoke the dynamics call wrapper, see the "API reference" section.

The code in Example A–12 illustrates the steps necessary to make dynamics calls.

Example A–12: Steps for making dynamics calls 
PROCEDURE emptyProcParam: 
  DEFINE INPUT         PARAMETER pcChar   AS CHARACTER  NO-UNDO. 
  DEFINE INPUT-OUTPUT  PARAMETER piInt    AS INTEGER    NO-UNDO. 
  DEFINE OUTPUT        PARAMETER phHndl   AS HANDLE     NO-UNDO. 
  piInt  = 35. 
  phHndl = THIS-PROCEDURE. 
  RETURN "Hello":U. 
END. 

The Parameter Holder temp-table contains a field for each parameter you want to pass. The Parameter Holder temp-table structure contains a field for each parameter and two extra fields: callReturnValue that contains the return value from the function or procedure and errReturnValue that contains a value only when an error occurs. The data types for the fields are the same as the data type of the parameter being referenced. The COLUMN-LABEL for the field contains the data type to be used for the call and the mode of the parameter. For example, INPUT, INPUT-OUTPUT, OUTPUT, or OUTPUT-APPEND.

If source parameters are provided to the setupTTFrom call, the initial values of the temp-table fields are set to the values of the source parameters so that it is not necessary to create a temp-table record in the Parameter Holder temp-table until the call is made. When the record is created, the initial value is derived from whatever was set.

The code in Example A–13 builds the parameters into a temp-table that is then used to create a parameter temp-table.

Example A–13: Creating the parameter holder temp-table
/* example 1 */ 
/* Include the temp-table for the call parameters */ 
{src/adm2/calltables.i} 
/* Run the target procedure persistently */ 
RUN calls.p PERSISTENT SET hProc. 
/* Create a record for each parameter */ 
DO TRANSACTION: 
  CREATE ttCallParam. 
  ASSIGN 
    ttCallParam.iParamNo   = 1 
    ttCallParam.cDataType  = "CHARACTER" 
    ttCallParam.cIOMode    = "INPUT" 
    ttCallParam.cCharacter = "aaa" 
  . 
  CREATE ttCallParam. 
  ASSIGN 
    ttCallParam.iParamNo   = 2 
    ttCallParam.cDataType  = "INTEGER" 
    ttCallParam.cIOMode    = "INPUT-OUTPUT" 
    ttCallParam.iInteger   = 12 
  . 
  CREATE ttCallParam. 
  ASSIGN 
    ttCallParam.iParamNo   = 3 
    ttCallParam.cDataType  = "HANDLE" 
    ttCallParam.cIOMode    = "OUTPUT" 
    ttCallParam.hHandle    = ? 
  . 
END. 
/* Step 1. Create a Parameter Holder temp-table for the call */ 
hTable = DYNAMIC-FUNCTION("setupTTFromTable" IN THIS-PROCEDURE, 
                 "ttParameters",   /* Temp-table name */ 
                 "CHARACTER",      /* Return value data type */ 
                 TEMP-TABLE ttCallParam:HANDLE). 
/* Step 2. Invoke the call */ 
RUN invokeCall IN THIS-PROCEDURE 
  ("emptyProcParam",        /* Name of internal procedure */ 
   hProc,                   /* Handle of the IN procedure */ 
   PROCEDURE-CALL-TYPE,     /* We're calling a procedure */ 
   hTable,                  /* Handle from setupTTFromTable */ 
   NO,                      /* Persistent */ 
   ?,                       /* Server */ 
   NO,                      /* Asynch */ 
   "",                      /* Event procedure for Asynch */ 
   ?,                       /* Event procedure context */ 
   OUTPUT iCall).           /* Call number */ 
/* Step 3. Obtain information about the call */ 
hCall = obtainCallInfo(iCall, OUTPUT cReturnValue, OUTPUT hTable). 
/* process the call information */ 
/* Step 4. Cleanup. 
   Delete all the call information except the Parameter Holder 
   temp-table */ 
RUN cleanupCall IN THIS-PROCEDURE  (iCall, "!T,*"). 
DELETE OBJECT hTable. 

The code in Example A–14 illustrates how parameters are derived from the signature and then set.

Example A–14: Deriving parameters from the signature 
/* Run the target procedure persistently */ 
RUN calls.p PERSISTENT SET hProc. 
/* Step 1. Create a Parameter Holder temp-table for the call 
   from the signature of the call that we want to make */ 
hTable = DYNAMIC-FUNCTION("setupTTFromSig" IN THIS-PROCEDURE, 
         "ttParameters",   /* Temp-table name */ 
         hProc,            /* Persistent procedure */ 
        "emptyProcParam",  /* Internal procedure */ 
         "",          /* Signature */ 
         ? ).        /* Handle to TT with initial values * 
/* Now set the parameter values. */ 
hTable:DEFAULT-BUFFER:BUFFER-CREATE(). 
hTable:DEFAULT-BUFFER:BUFFER-FIELD("pcChar"):BUFFER-VALUE = "aaa". 
hTable:DEFAULT-BUFFER:BUFFER-FIELD("pcInt"):BUFFER-VALUE = 12. 
hTable:DEFAULT-BUFFER:BUFFER-FIELD("phHndl"):BUFFER-VALUE = ?. 
hTable:DEFAULT-BUFFER:BUFFER-RELEASE(). 
/* Step 2. Invoke the call */ 
RUN invokeCall IN THIS-PROCEDURE 
  ("emptyProcParam",        /* Name of internal procedure */ 
   hProc,                   /* Handle of the IN procedure */ 
   PROCEDURE-CALL-TYPE,     /* We're calling a procedure */ 
   hTable,                  /* Handle from setupTTFromTable */ 
   NO,                      /* Persistent */ 
   ?,                       /* Server */ 
   NO,                      /* Asynch */ 
   "",                      /* Event procedure for Asynch */ 
   ?,                       /* Event procedure context */ 
   OUTPUT iCall).           /* Call number */ 
/* Step 3. Obtain information about the call */ 
hCall = obtainCallInfo(iCall, OUTPUT cReturnValue, OUTPUT hTable). 
/* process the call information */ 
/* Step 4. Cleanup */ 
RUN cleanupCall IN THIS-PROCEDURE  (iCall, "*").  

In Example A–15, the parameters are derived from a string that is passed in to create the dynamics temp-table.

Example A–15: Deriving parameters from a string to create a dynamics temp-table 
/* Run the target procedure persistently */ 
RUN calls.p PERSISTENT SET hProc. 
/* Step 1. Create a Parameter Holder temp-table for the call 
   from the string that we pass into the call */ 
hTable = DYNAMIC-FUNCTION("setupTTFromString" IN THIS-PROCEDURE, 
                 "ttParameters",   /* Temp-table name */ 
                 "CHARACTER",      /* RETURN-VALUE data type */ 
"INPUT CHARACTER 'aaa', INPUT INTEGER '12', INPUT HANDLE '?'").  
/* Parameter string */ 
/* Step 2. Invoke the call */ 
RUN invokeCall IN THIS-PROCEDURE 
  ("emptyProcParam",        /* Name of internal procedure */ 
   hProc,                   /* Handle of the IN procedure */ 
   PROCEDURE-CALL-TYPE,     /* We're calling a procedure */ 
   hTable,                  /* Handle from setupTTFromTable */ 
   NO,                      /* Persistent */ 
   ?,                       /* Server */ 
   NO,                      /* Asynch */ 
   "",                      /* Event procedure for Asynch */ 
   ?,                       /* Event procedure context */ 
   OUTPUT iCall).           /* Call number */ 
/* Step 3. Obtain information about the call */ 
hCall = obtainCallInfo(iCall, OUTPUT cReturnValue, OUTPUT hTable). 
/* process the call information */ 
/* Step 4. Cleanup */ 
RUN cleanupCall IN THIS-PROCEDURE  (iCall, "*"). 


Copyright © 2005 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095